package driver

import (
	"gitee.com/gousing/cache/storage"
)

// ---------------------------------------
// MemoryCache 简单集合实现
// SString String 字符串集合
// SInt    Int64 数值集合
// ---------------------------------------

// SStringAdd 向指定 key 的 String 集合添加一个或多个成员元素
//   - 如果指定 key 的集合不存在, 则新建集合并添加值到集合
//   - 如果指定 key 不是一个 String 集合, 则返回错误
//   - 如果指定 key 的集合存在, 则添加值到集合
//   - 如果 items为空, 则什么也不做, 直接返回nil
func (c *MemoryCache) SStringAdd(key string, items ...string) error {
	if key == "" {
		return storage.ErrKeyIsEmpty
	}
	if len(items) == 0 {
		return nil
	}
	shard := c.getCacheShard(key)
	shard.mu.Lock()
	defer shard.mu.Unlock()
	// 读取缓存值
	node, err := c._getNode(shard, key)
	if err != nil {
		// 集合不存在: 则新建一个空白缓存项, 并设置类型为 storage.KindSetString
		if err := c._setOptions(shard, key, ""); err != nil {
			return err
		}
		node, err = c._getNode(shard, key)
		if err != nil {
			return storage.ErrValueNotSetString
		}
		// 将缓存类型设置为 storage.KindSetString, 因为 _setOptions 类型初始化为了字符串
		node.kind = storage.KindSetString
		node.value = map[string]struct{}{}
	}
	if err != nil || node.kind != storage.KindSetString {
		return storage.ErrValueNotSetString
	}
	if data, ok := node.value.(map[string]struct{}); ok {
		for _, item := range items {
			data[item] = struct{}{}
		}
		return nil
	}
	return storage.ErrValueNotSetString
}

// SStringRemove 从指定 key 的 String 集合中移除一个或多个成员
//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回错误
//   - 如果items为空, 则什么也不做, 直接返回nil
func (c *MemoryCache) SStringRemove(key string, items ...string) error {
	if key == "" {
		return storage.ErrKeyIsEmpty
	}

	shard := c.getCacheShard(key)
	shard.mu.Lock()
	defer shard.mu.Unlock()

	// 读取缓存值
	node, err := c._getNode(shard, key)
	// 集合不存在
	if err != nil {
		return err
	}
	// 集合类型不是 String 集合
	if node.kind != storage.KindSetString {
		return storage.ErrValueNotSetString
	}
	if len(items) == 0 {
		return nil
	}
	if data, ok := node.value.(map[string]struct{}); ok {
		for _, item := range items {
			delete(data, item)
		}
		return nil
	}
	return storage.ErrValueNotSetString
}

// SStringClear 清空指定 key 的 String 集合
//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回错误
func (c *MemoryCache) SStringClear(key string) error {
	if key == "" {
		return storage.ErrKeyIsEmpty
	}
	shard := c.getCacheShard(key)
	shard.mu.Lock()
	defer shard.mu.Unlock()

	// 读取缓存值
	node, err := c._getNode(shard, key)
	// 集合不存在
	if err != nil {
		return err
	}
	// 集合类型不是 String 集合
	if node.kind != storage.KindSetString {
		return storage.ErrValueNotSetString
	}
	node.value = map[string]struct{}{}
	return nil
}

// SStringContains 判断一个或多个成员是否全部在指定 key 的 String 集合中
//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回 false
//   - 查询多个成员, 任意一个成员不在集合中, 则返回 false
func (c *MemoryCache) SStringContains(key string, items ...string) bool {
	if key == "" {
		return false
	}
	if len(items) == 0 {
		return false
	}
	shard := c.getCacheShard(key)
	shard.mu.Lock()
	defer shard.mu.Unlock()

	// 读取缓存值
	node, err := c._getNode(shard, key)
	// 集合不存在
	if err != nil {
		return false
	}
	// 集合类型不是 String 集合
	if node.kind != storage.KindSetString {
		return false
	}
	if data, ok := node.value.(map[string]struct{}); ok {
		for _, item := range items {
			// 有一个成员不在集合中, 直接返回 false
			if _, exists := data[item]; !exists {
				return false
			}
		}
		return true
	}
	return false
}

// SStringContainsSome 判断一个或多个成员的中任意一个成员是否在指定 key 的 String 集合中
//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回 false
//   - 查询多个成员, 任意一个成员存在集合中, 则返回 true
func (c *MemoryCache) SStringContainsSome(key string, items ...string) bool {
	if key == "" {
		return false
	}
	if len(items) == 0 {
		return false
	}
	shard := c.getCacheShard(key)
	shard.mu.Lock()
	defer shard.mu.Unlock()

	// 读取缓存值
	node, err := c._getNode(shard, key)
	// 集合不存在
	if err != nil {
		return false
	}
	// 集合类型不是 String 集合
	if node.kind != storage.KindSetString {
		return false
	}
	if data, ok := node.value.(map[string]struct{}); ok {
		for _, item := range items {
			// 有一个成员在集合中, 直接返回 true
			if _, exists := data[item]; exists {
				return true
			}
		}
	}
	return false
}

// SStringMembers 获取指定 key 的 String 集合的所有成员
//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回错误
func (c *MemoryCache) SStringMembers(key string) ([]string, error) {
	if key == "" {
		return []string{}, storage.ErrKeyIsEmpty
	}
	shard := c.getCacheShard(key)
	shard.mu.Lock()
	defer shard.mu.Unlock()
	// 读取缓存值
	node, err := c._getNode(shard, key)
	// 集合不存在
	if err != nil {
		return []string{}, err
	}
	// 集合类型不是 String 集合
	if node.kind != storage.KindSetString {
		return []string{}, storage.ErrValueNotSetString
	}
	// 集合存在: 则返回所有成员
	if data, ok := node.value.(map[string]struct{}); ok {
		items := make([]string, len(data))
		i := 0
		for k := range data {
			items[i] = k
			i++
		}
		return items, nil
	}
	return []string{}, storage.ErrValueNotSetString
}

// SStringTraverse 遍历指定 key 的 String 集合的所有成员
//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回错误
//   - fn 签名是 iter.Seq[string], 迭代过程中, 返回 false 则停止遍历
func (c *MemoryCache) SStringTraverse(key string, fn func(string) bool) error {
	if key == "" {
		return storage.ErrKeyIsEmpty
	}
	if fn == nil {
		return storage.ErrTraverseFnIsNil
	}
	shard := c.getCacheShard(key)
	shard.mu.Lock()
	// 读取缓存值
	node, err := c._getNode(shard, key)
	// 集合不存在
	if err != nil {
		shard.mu.Unlock()
		return err
	}
	// 集合类型不是 String 集合
	if node.kind != storage.KindSetString {
		shard.mu.Unlock()
		return storage.ErrValueNotSetString
	}
	members, ok := node.value.(map[string]struct{})
	if !ok {
		shard.mu.Unlock()
		return storage.ErrValueNotSetString
	}
	// 集合存在: 复制一份副本数据
	// 避免在迭代过程中被修改导致数据不一致问题 (并发修改)
	data := make([]string, 0, len(members))
	for item := range members {
		data = append(data, item)
	}
	// 释放锁后开始迭代
	shard.mu.Unlock()
	for _, item := range data {
		if !fn(item) {
			break
		}
	}
	return nil
}

// SStringSize 获取指定 key 的 String 集合的成员数量
//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回错误
func (c *MemoryCache) SStringSize(key string) (int64, error) {
	if key == "" {
		return 0, storage.ErrKeyIsEmpty
	}
	shard := c.getCacheShard(key)
	shard.mu.Lock()
	defer shard.mu.Unlock()
	// 读取缓存值
	node, err := c._getNode(shard, key)
	// 集合不存在
	if err != nil {
		return 0, err
	}
	// 集合存在: 则返回成员数量
	if data, ok := node.value.(map[string]struct{}); ok {
		return int64(len(data)), nil
	}
	return 0, storage.ErrValueNotSetString
}

// SIntAdd 向指定 key 的 Int64 集合添加一个或多个成员元素
//   - 如果指定 key 的集合不存在, 则新建集合并添加值到集合
//   - 如果指定 key 不是一个 Int64 集合, 则返回错误
//   - 如果指定 key 的集合存在, 则添加值到集合
//   - 如果 items为空, 则什么也不做, 直接返回nil
func (c *MemoryCache) SIntAdd(key string, items ...int64) error {
	if key == "" {
		return storage.ErrKeyIsEmpty
	}
	if len(items) == 0 {
		return nil
	}
	shard := c.getCacheShard(key)
	shard.mu.Lock()
	defer shard.mu.Unlock()
	// 读取缓存值
	node, err := c._getNode(shard, key)
	if err != nil {
		// 集合不存在: 则新建一个空白缓存项, 并设置类型为 storage.KindSetInt
		if err := c._setOptions(shard, key, ""); err != nil {
			return err
		}
		node, err = c._getNode(shard, key)
		if err != nil {
			return storage.ErrValueNotSetInt
		}
		// 将缓存类型设置为 storage.KindSetInt, 因为 _setOptions 类型初始化为了字符串
		node.kind = storage.KindSetInt
		node.value = map[int64]struct{}{}
	}
	if err != nil || node.kind != storage.KindSetInt {
		return storage.ErrValueNotSetInt
	}
	if data, ok := node.value.(map[int64]struct{}); ok {
		for _, item := range items {
			data[item] = struct{}{}
		}
		return nil
	}
	return storage.ErrValueNotSetInt
}

// SIntRemove 从指定 key 的 Int64 集合中移除一个或多个成员
//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回错误
//   - 如果items为空, 则什么也不做, 直接返回nil
func (c *MemoryCache) SIntRemove(key string, items ...int64) error {
	if key == "" {
		return storage.ErrKeyIsEmpty
	}

	shard := c.getCacheShard(key)
	shard.mu.Lock()
	defer shard.mu.Unlock()

	// 读取缓存值
	node, err := c._getNode(shard, key)
	// 集合不存在
	if err != nil {
		return err
	}
	// 集合类型不是 Int64 集合
	if node.kind != storage.KindSetInt {
		return storage.ErrValueNotSetInt
	}
	if len(items) == 0 {
		return nil
	}
	if data, ok := node.value.(map[int64]struct{}); ok {
		for _, item := range items {
			delete(data, item)
		}
		return nil
	}
	return storage.ErrValueNotSetInt
}

// SIntClear 清空指定 key 的 Int64 集合
//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回错误
func (c *MemoryCache) SIntClear(key string) error {
	if key == "" {
		return storage.ErrKeyIsEmpty
	}
	shard := c.getCacheShard(key)
	shard.mu.Lock()
	defer shard.mu.Unlock()
	// 读取缓存值
	node, err := c._getNode(shard, key)
	// 集合不存在
	if err != nil {
		return err
	}
	// 集合类型不是 Int64 集合
	if node.kind != storage.KindSetInt {
		return storage.ErrValueNotSetInt
	}
	node.value = make(map[int64]struct{})
	return nil
}

// SIntContains 判断一个或多个成员是否全部在指定 key 的 Int64 集合中
//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回 false
//   - 查询多个成员, 任意一个成员不在集合中, 则返回 false
func (c *MemoryCache) SIntContains(key string, items ...int64) bool {
	if key == "" {
		return false
	}
	if len(items) == 0 {
		return false
	}
	shard := c.getCacheShard(key)
	shard.mu.Lock()
	defer shard.mu.Unlock()

	// 读取缓存值
	node, err := c._getNode(shard, key)
	// 集合不存在
	if err != nil {
		return false
	}
	// 集合类型不是 Int64 集合
	if node.kind != storage.KindSetInt {
		return false
	}
	if data, ok := node.value.(map[int64]struct{}); ok {
		for _, item := range items {
			// 有一个成员不在集合中, 直接返回 false
			if _, exists := data[item]; !exists {
				return false
			}
		}
		return true
	}
	return false
}

// SIntContainsSome 判断一个或多个成员的中任意一个成员是否在指定 key 的 Int64 集合中
//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回 false
//   - 查询多个成员, 任意一个成员存在集合中, 则返回 true
func (c *MemoryCache) SIntContainsSome(key string, items ...int64) bool {
	if key == "" {
		return false
	}
	if len(items) == 0 {
		return false
	}
	shard := c.getCacheShard(key)
	shard.mu.Lock()
	defer shard.mu.Unlock()

	// 读取缓存值
	node, err := c._getNode(shard, key)
	// 集合不存在
	if err != nil {
		return false
	}
	// 集合类型不是 Int64 集合
	if node.kind != storage.KindSetInt {
		return false
	}
	if data, ok := node.value.(map[int64]struct{}); ok {
		for _, item := range items {
			// 有一个成员在集合中, 直接返回 true
			if _, exists := data[item]; exists {
				return true
			}
		}
	}
	return false
}

// SIntMembers 获取指定 key 的 Int64 集合的所有成员
//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回错误
func (c *MemoryCache) SIntMembers(key string) ([]int64, error) {
	if key == "" {
		return []int64{}, storage.ErrKeyIsEmpty
	}
	shard := c.getCacheShard(key)
	shard.mu.Lock()
	defer shard.mu.Unlock()
	// 读取缓存值
	node, err := c._getNode(shard, key)
	// 集合不存在
	if err != nil {
		return []int64{}, err
	}
	// 集合类型不是 Int64 集合
	if node.kind != storage.KindSetInt {
		return []int64{}, storage.ErrValueNotSetInt
	}
	// 集合存在: 则返回所有成员
	if data, ok := node.value.(map[int64]struct{}); ok {
		items := make([]int64, len(data))
		i := 0
		for k := range data {
			items[i] = k
			i++
		}
		return items, nil
	}
	return []int64{}, storage.ErrValueNotSetInt
}

// SIntTraverse 遍历指定 key 的 Int64 集合的所有成员
//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回错误
//   - fn 签名是 iter.Seq[int64], 迭代过程中, 返回 false 则停止遍历
func (c *MemoryCache) SIntTraverse(key string, fn func(int64) bool) error {
	if key == "" {
		return storage.ErrKeyIsEmpty
	}
	if fn == nil {
		return storage.ErrTraverseFnIsNil
	}
	shard := c.getCacheShard(key)
	shard.mu.Lock()
	// 读取缓存值
	node, err := c._getNode(shard, key)
	// 集合不存在
	if err != nil {
		shard.mu.Unlock()
		return err
	}
	// 集合类型不是 Int64 集合
	if node.kind != storage.KindSetInt {
		shard.mu.Unlock()
		return storage.ErrValueNotSetInt
	}
	members, ok := node.value.(map[int64]struct{})
	if !ok {
		shard.mu.Unlock()
		return storage.ErrValueNotSetInt
	}
	// 集合存在: 复制一份副本数据
	// 避免在迭代过程中被修改导致数据不一致问题 (并发修改)
	data := make([]int64, 0, len(members))
	for k := range members {
		data = append(data, k)
	}
	// 释放锁后, 开始迭代所有成员
	shard.mu.Unlock()
	for _, k := range data {
		if !fn(k) {
			break
		}
	}
	return nil
}

// SIntSize 获取指定 key 的 Int64 集合的成员数量
//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回错误
func (c *MemoryCache) SIntSize(key string) (int64, error) {
	if key == "" {
		return 0, storage.ErrKeyIsEmpty
	}
	shard := c.getCacheShard(key)
	shard.mu.Lock()
	defer shard.mu.Unlock()
	// 读取缓存值
	node, err := c._getNode(shard, key)
	// 集合不存在
	if err != nil {
		return 0, err
	}
	// 集合存在: 则返回成员数量
	if data, ok := node.value.(map[int64]struct{}); ok {
		return int64(len(data)), nil
	}
	return 0, storage.ErrValueNotSetInt
}
